#ifndef BLOCK_QUEUE_HPP
#define BLOCK_QUEUE_HPP

#include <queue>
#include <pthread.h>

template<typename T>
class BlockQueue
{
public:
    BlockQueue(int cap)
    {
        _cap = cap;
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_consumer_cond, nullptr);
        pthread_cond_init(&_productor_cond, nullptr);
    }

    bool IsFull()
    {
        return _q.size() == _cap;
    }

    bool IsEmpty()
    {
        return _q.empty();
    }

    void Enqueue(T& data)
    {
        pthread_mutex_lock(&_mutex);
        while(IsFull())
        {
            pthread_cond_wait(&_productor_cond, &_mutex);
        }

        _q.push(data);

        pthread_cond_signal(&_consumer_cond);//生产了继续消费
        pthread_mutex_unlock(&_mutex);
    }

    void Pop(T* data)
    {
        pthread_mutex_lock(&_mutex);
        while(IsEmpty())
        {
            pthread_cond_wait(&_consumer_cond, &_mutex);
        }

        *data = _q.front();
        _q.pop();

        pthread_cond_signal(&_productor_cond);//消费了继续生产
        pthread_mutex_unlock(&_mutex);
    }

    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_consumer_cond);
        pthread_cond_destroy(&_productor_cond);
    }

private:
    std::queue<T> _q;    //队列存储数据
    int _cap;            //阻塞队列的容量
    pthread_mutex_t _mutex;
    pthread_cond_t _consumer_cond;
    pthread_cond_t _productor_cond;
};

#endif